package dslProgramGen.util;

import dslProgramGen.DslExpressedMethod;
import methodCallTreeGen.MethodNode;
import methodCallTreeGen.Node;
import methodCallTreeGen.NodeType;

import java.util.List;

import static dslProgramGen.DslProgramGen.isGenJavaProgram;

/**
 * 作为ClearRedundantMethods类的工具类，提炼出可能被其他类使用的方法
 */
public class ClearRedundantMethodsUtil {

    /**
     * 对DslExpressedMethod中的函数体调用的某个函数名重命名，假如之前某行调用的函数旧名为A_v0,现在重命名为newCallMethodName为A_v4
     *
     * @param dslExpressedMethod dslExpressedMethod里的函数体调用的oldCallMethoName需要重命名
     * @param oldCallMethoName   之前调用的函数名称
     * @param newCallMethodName  调用的函数重命名后的新名称
     */
    public static void renameCallMethodNameInMethodContentList(DslExpressedMethod dslExpressedMethod, String oldCallMethoName, String newCallMethodName) {
        List<String> methodContentList = dslExpressedMethod.methodContentList;
        // 对dslExpressedMethod函数体每一行遍历
        for (int i = 0; i < methodContentList.size(); i++) {
            String ithDslStatement = methodContentList.get(i);
            if (ithDslStatement.contains(oldCallMethoName+"(")) {
                // 将调用的旧函数名改成新函数名
                ithDslStatement = ithDslStatement.replace(oldCallMethoName, newCallMethodName);
                methodContentList.set(i, ithDslStatement);
            }
        }
    }


    /**
     * 获得一个methodNode的第n个调用的子函数
     *
     * @param methodNode   待处理的methodNode
     * @param nthSubMethod 获得第几个子函数
     * @return
     */
    public static MethodNode getNthSubMethodNode(MethodNode methodNode, int nthSubMethod) {
        int subMethodNodeNum = 0;
        for (Node node : methodNode.contentNodeList) {
            if (node.nodeType == NodeType.METHOD) {
                if (subMethodNodeNum == nthSubMethod) {
                    return (MethodNode) node;
                }
                subMethodNodeNum++;
            }
        }
        return null;
    }

    /**
     * 判断一个methodNode有没有调用其他函数
     * @param methodNode 待判断的methodNode
     * @return 返回true表示调用了其他函数，false表示没有调用其他函数
     */
    public static boolean hasSubMethodNode(MethodNode methodNode) {
        for (Node node : methodNode.contentNodeList) {
            if (node.nodeType == NodeType.METHOD) {
                return true;
            }
        }
        return false;
    }

    /**
     * 计算methodNode调用了多少子函数
     *
     * @param methodNode 待计算的methodNode
     * @return 调用子函数的个数
     */
    public static int getSubMethodNum(MethodNode methodNode) {
        int cntSubMethodNum = 0;
        for (Node node : methodNode.contentNodeList) {
            if (node.nodeType == NodeType.METHOD) {
                cntSubMethodNum++;
            }
        }
        return cntSubMethodNum;
    }

    /**
     * 判断一个DslStatement是否是函数调用
     *
     * @param dslStatementString
     * @return
     */
    public static boolean isMethodCallDslStatement(String dslStatementString) {
        if (isGenJavaProgram) {
            // 若生成java程序,dslStatementString含有(与 ),且不含有spawn语句
            if (dslStatementString.contains("(") && dslStatementString.contains(")") && !dslStatementString.contains("spawn ")) {
                return true;
            }
        } else {
            // 若生成MOP程序 含有( 与 )，不应该含有NewInstance或 NewArray 或 spawn methodName(objectVar);
            if (dslStatementString.contains("(") && dslStatementString.contains(")") &&
                    !dslStatementString.contains("NewInstance") && !dslStatementString.contains("NewArray") && !dslStatementString.contains("spawn ")) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断两个List内容是否一样
     *
     * @param list1
     * @param list2
     * @return
     */
    public static boolean isTwoListEqual(List<String> list1, List<String> list2) {
        if (list1.size() != list2.size()) {
            // 如果两个list的size不同，则不相同
            return false;
        } else {
            for (int i = 0; i < list1.size(); i++) {
                if (!list1.get(i).equals(list2.get(i))) {
                    return false;
                }
            }
        }
        return true;
    }
}
